package hxm.monads;

import hxm.monads.FutureMonad;

/**
 * This monad resolves the monadic type at runtime.
 * 
 * @author Simon Krajewski
 */

class DynamicMonad 
{
	static public function bind<A, B>(a:Dynamic, f:A -> Dynamic):Dynamic
	{
		return getMonadType(a).bind(a, f);
	}
	
	static public function map<A, B>(a:List<A>, f:A->B):List<B>
	{
		return getMonadType(a).map(a, f);
	}
	
	static public function yield<A>(a:A):Dynamic
	{
		return getMonadType(a).yield(a);
	}
	
	static function getMonadType(a:Dynamic):Dynamic
	{
		if (a == null)
			return IdentityMonad;
			
		if (Std.is(a, List))
			return ListMonad;
		else if (Std.is(a, Array))
			return ArrayMonad;
		else if (Std.is(a, Future))
			return FutureMonad;
		else if (Reflect.hasField(a, "next") && Reflect.hasField(a, "hasNext"))
			return IteratorMonad;
		return IdentityMonad;		
	}
}